﻿namespace Vibstudio.NetConfigurator.Extensions
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    public static class ConfigurationExtensions
    {
        #region Url methods

        public static bool  IsUrl(this string str)
        {
            bool result = false;

            foreach (CommunicationProtocol protocol in Enum.GetValues(typeof(CommunicationProtocol)))
            {
                if (str.StartsWith(string.Format("{0}://", Enum.GetName(typeof (CommunicationProtocol), protocol).ToLower())))
                    result = true;
            }

            return result;
        }

        public static bool IsRelativeUrl(this string str)
        {
            return str.Substring(str.Length - 1, 1) == "/";
        }

        public static bool IsAspnetUrl(this string str)
        {
            bool result = false;

            foreach (DotNetUriExtension uriExtension in Enum.GetValues(typeof(DotNetUriExtension)))
            {
                string extension = string.Format(".{0}",
                                                 Enum.GetName(typeof (DotNetUriExtension), uriExtension).ToLower());
                if (str.Contains(extension))
                    result = true;
            }

            return result;
        }


        public static bool IsExceptionUrl(this string str, IEnumerable<string> exceptions)
        {
            return
                exceptions.Any(
                    exception =>
                    str.ToLower().Contains(exception.ToLower()) || exception.ToLower().Contains(str.ToLower()));
        }

        public static bool IsRootUrl(this string str)
        {
            return new Uri(str).Segments.Length <= 1;
        }

        #endregion

        #region Domain methods

        public static string GetDomain(this string str)
        {
            string domain = ExtractDomain(str.GetHost());

            if (string.IsNullOrEmpty(domain))
                domain = ExtractDomain(str);

            return domain;
        }

        private static string ExtractDomain(string host)
        {
            string[] hostSplit = host.Split('.');
            string domain = hostSplit.Length >= 2
                                ? string.Format("{0}.{1}", hostSplit[hostSplit.Length - 2],
                                                hostSplit[hostSplit.Length - 1])
                                : hostSplit[0];
            return domain;
        }

        #endregion

        #region Host methods

        public static string GetHost(this string str)
        {
            if (str.IsUrl())
            {
                var uri = new Uri(str);
                return uri.Authority;
            }

            return str;
        }

        public static string ReplaceHost(this string str, string replacement)
        {
            string host = str.GetHost();
            string substituteHost = replacement.GetHost();
            int pos = str.ToLower().IndexOf(host, StringComparison.Ordinal);
            if (pos < 0) return str;

            var builder = new StringBuilder();
            builder.Append(str.Substring(0, pos));
            builder.Append(substituteHost);
            builder.Append(str.Substring(pos + host.Length));

            return builder.ToString();
        }

        public static string ReplaceDomain(this string str, string domain)
        {
            return str.Replace(str.GetDomain(), domain);
        }

        #endregion

        #region ResourceName methods

        public static string GetResourceName(this string str)
        {
            string resourceName = string.Empty;

            if (str.IsUrl())
            {
                var uri = new Uri(str);
                string[] uriSegments = uri.Segments;
                if (uriSegments.Length > 1)
                {
                    string segment = uriSegments[1];
                    if (segment.Substring(segment.Length - 1, 1) == @"/")
                        resourceName = segment.Substring(0, segment.Length - 1);
                }
            }

            return resourceName;
        }

        public static string ReplaceResourceName(this string str, string replacement)
        {
            string resourceName = str.GetResourceName();
            int pos = str.IndexOf(resourceName, StringComparison.Ordinal);
            if (pos < 0) return str;

            var builder = new StringBuilder();
            builder.Append(str.Substring(0, pos));
            builder.Append(replacement);
            builder.Append(str.Substring(pos + resourceName.Length));

            return builder.ToString();
        }

        #endregion

        #region Other methods

        public static string ReplaceConnectionString(this string str, Dictionary<string, string> dictionary)
        {
            var result = new StringBuilder();

            string[] keyValuePairs = str.Split(';');
            foreach (string s in keyValuePairs)
            {
                string value = string.Empty;
                string sTemp = s;
                foreach (KeyValuePair<string, string> pair in dictionary.Where(pair => sTemp.StartsWith(pair.Key)))
                {
                    value = s.Replace(str.ExtractValue(pair.Key), pair.Value);
                    break;
                }

                result.AppendFormat("{0};", !string.IsNullOrEmpty(value) ? value : s);
            }

            return result.ToString().Remove(result.Length - 1, 1);
        }

        public static string ExtractValue(this string str, string key)
        {
            int indexStartValue = str.IndexOf(key, StringComparison.Ordinal) + key.Length + 1;
            char[] substring = str.Substring(indexStartValue).ToCharArray();

            int valueLenght = 0;
            foreach (char c in substring)
            {
                if (c != ';') valueLenght++;
                else break;
            }

            return str.Substring(indexStartValue, valueLenght);
        }

        public static string Capitalize(this string str)
        {
            if (string.IsNullOrEmpty(str))
            {
                return string.Empty;
            }

            var builder = new StringBuilder();

            builder.AppendFormat("{0}{1}",
                                 char.ToUpper(str[0]),
                                 str.ToLower().Substring(1));

            return builder.ToString();
        }

        public static string Generalize(this string str)
        {
            if (string.IsNullOrEmpty(str)) return string.Empty;

            return !str.Contains("#")
                       ? str
                       : str.Substring(0, str.IndexOf("#", StringComparison.Ordinal));
        }

        #endregion
    }
}